# 标定窗口
import struct
import threading
import time
from threading import Thread

import wx
from app import utils, UI

logMgr = utils.logMgr
btnState = {0: ("标定第一点", "#F5F5F5"),
            1: ("标定第二点", "#CFCFCF"),
            2: ("等待计算完成", "#CCCCCC"),
            3: ("重新标定", "#F0F0F0")
            }


class CalWindow(wx.BoxSizer):
    def __init__(self, ctx):
        super().__init__(orient=wx.HORIZONTAL)
        self.ctx = ctx
        self.state = 0
        leftBox = self.initLeft(ctx)
        rightBox = self.initRight(ctx)

        self.Add(leftBox, 1, flag=wx.EXPAND)
        self.Add(rightBox, 4, flag=wx.EXPAND)

    def initLeft(self, ctx):
        leftBox = wx.BoxSizer(wx.VERTICAL)

        ratioBox = wx.BoxSizer(wx.HORIZONTAL)
        ratioBtn = wx.Button(ctx, -1, "发射功率设置", size=(100, 20))
        ratioBtn.Bind(wx.EVT_BUTTON, self.setEmitRatio)
        self.et_emit_ratio = wx.TextCtrl(ctx, -1, "", size=(40, 20))
        ratioBox.Add(ratioBtn, 0, wx.LEFT, border=0)
        ratioBox.Add(self.et_emit_ratio, 0, wx.LEFT, border=20)
        leftBox.Add(ratioBox, 0, wx.LEFT | wx.TOP, border=15)

        p1Box = wx.BoxSizer(wx.HORIZONTAL)
        p1Box.Add(wx.StaticText(ctx, -1, label="p1_temp:", size=(60, 20)))
        self.et_p1 = wx.TextCtrl(ctx, -1, value="", size=(100, 20))
        p1Box.Add(self.et_p1, 0, wx.EXPAND)
        leftBox.Add(p1Box, 0, wx.LEFT | wx.TOP, border=15)

        p2Box = wx.BoxSizer(wx.HORIZONTAL)
        p2Box.Add(wx.StaticText(ctx, -1, label="p2_temp:", size=(60, 20)))
        self.et_p2 = wx.TextCtrl(ctx, -1, value="", size=(100, 20))
        p2Box.Add(self.et_p2, 0, wx.EXPAND)
        leftBox.Add(p2Box, 0, wx.LEFT | wx.TOP | wx.BOTTOM, border=15)

        self.setPointBtn = wx.Button(ctx, -1, "重设p1 p2", pos=(120, 0), size=(120, 30))
        self.setPointBtn.Bind(wx.EVT_BUTTON, self.setPoint12)
        leftBox.Add(self.setPointBtn, 0, flag=wx.LEFT, border=30)

        self.calFirstBtn = wx.Button(ctx, -1, "标定第一点", pos=(120, 0), size=(120, 60))
        self.calFirstBtn.Bind(wx.EVT_BUTTON, self.calFirst)
        leftBox.Add(self.calFirstBtn, 0, flag=wx.LEFT | wx.TOP, border=30)

        self.calSecondBtn = wx.Button(ctx, -1, "退出标定", pos=(120, 0), size=(120, 60))
        self.calSecondBtn.Bind(wx.EVT_BUTTON, self.onExit)
        self.calSecondBtn.SetBackgroundColour((0, 162, 232))
        self.calSecondBtn.SetForegroundColour((255, 255, 255))
        leftBox.Add(self.calSecondBtn, 0, flag=wx.LEFT | wx.TOP, border=30)
        return leftBox

    def initRight(self, ctx):
        rightBox = wx.BoxSizer(wx.VERTICAL)
        self.et_receive = wx.TextCtrl(ctx, -1, value="", size=(280, 230), style=wx.TE_MULTILINE)
        self.et_receive.SetEditable(False)
        self.et_receive.SetBackgroundColour((233, 233, 233))

        font = self.ctx.GetFont()
        font.SetPointSize(15)
        self.et_receive.SetFont(font)
        rightBox.Add(self.et_receive, 0, flag=wx.EXPAND | wx.TOP, border=30)

        return rightBox

    def setEmitRatio(self, e):
        ratio = 0.0
        val = self.et_emit_ratio.GetValue()
        try:
            ratio = float(val)
        except Exception:
            pass
        print("ratio=>" + str(ratio))
        if (ratio <= 0 or ratio > 1.0):
            wx.MessageBox("发射功率为0-1.0的小数")
            return
        req = '%0.1f' % ratio
        self.ctx.master.fun_emit_ratio(ratio)  # 写入功率
        time.sleep(0.1)
        data = self.ctx.master.readReg(addr=0x2C, cntbyte=4, datatypelen=1)
        datab = struct.unpack('<f', bytes(data))
        resp = '%.1f' % datab[0]
        if req == resp:
            wx.MessageBox("设置成功")
            self.et_emit_ratio.SetValue(resp)
        else:
            wx.MessageBox("设置失败")


    def setPoint12(self, e):
        p1str = self.et_p1.GetValue()
        p2str = self.et_p2.GetValue()
        if '.' in p1str or '.' in p2str:
            wx.MessageBox("请输入整数")
            return
        p1 = 0
        p2 = 0
        try:
            p1 = int(p1str)
            p2 = int(p2str)
        except ValueError:
            wx.MessageBox("请输入0-255的整数")
            return

        if (p1 > 255 or p1 <= 0) or (p2 > 255 or p2 < 0):
            wx.MessageBox("请输入0-255的整数")
            return

        self.ctx.master.fun_cal_obj_temp(p1, p2)
        time.sleep(0.1)
        p1res = self.ctx.master.readReg(addr=0x29, cntbyte=2, datatypelen=1)[0]
        p2res = self.ctx.master.readReg(addr=0x29, cntbyte=2, datatypelen=1)[1]
        if p1 == p1res and p2 == p2res:
            wx.MessageBox("设置成功", style=wx.OK | wx.CENTRE)
        else:
            wx.MessageBox("设置失败")

    def calFirst(self, e):
        if self.state == 0:  # 标定就绪状态
            if self.ctx.master.calFirst():
                self.appendText("第一点标定成功")
                self.state = 1
            else:
                self.appendText("第一点标定失败", err=True)
        elif self.state == 1:  # 第一点标定完成
            if self.ctx.master.calSecond():
                self.appendText("第二点标定成功")
                self.state = 2
                th = threading.Thread(target=self.getCalParams, args=())
                th.start()
            else:
                self.appendText("第二点标定失败", err=True)
        elif self.state == 3:  # 第二点标定完成,重新进入标定
            if self.ctx.master.calMode():
                self.state = 0
                self.et_receive.SetValue("重新开始标定\n")
        self.notifyButton()

    def notifyButton(self):
        self.calFirstBtn.SetLabel(btnState.get(self.state)[0])
        self.calFirstBtn.SetBackgroundColour(btnState.get(self.state)[1])
        self.calFirstBtn.Enable(self.state != 2)

    def calSecond(self, e):
        if self.ctx.master.calSecond():
            self.appendText("第二点标定成功")
            th = threading.Thread(target=self.getCalParams, args=())
            th.start()
        else:
            self.appendText("第二点标定失败", err=True)

    def getCalParams(self):
        time.sleep(2)
        self.state = 3
        self.appendText("计算完成")
        self.notifyButton()
        res = self.ctx.master.getCalParams()
        logMgr.print(res)
        self.et_receive.SetValue(res)

    def onExit(self, e):
        if self.ctx.master.exitCalMode():
            self.hide()
            self.ctx.root.Show(0)
            self.ctx.root.Show(1)
            self.ctx.root.Show(2)
            self.ctx.root.Layout()

    def hide(self):
        for i in range(0, self.GetItemCount()):
            self.Hide(i)
        self.Layout()

    def show(self):
        for i in range(0, self.GetItemCount()):
            self.Show(i)
        self.Layout()
        self.initData()

    def initData(self):
        self.state = 0
        self.notifyButton()
        self.et_receive.SetValue("")
        arr = self.ctx.master.readReg(addr=0x29, cntbyte=2, datatypelen=1)
        p1 = arr[0]
        p2 = arr[1]
        self.et_p1.SetValue(str(p1))
        self.et_p2.SetValue(str(p2))
        # 获取发射功率
        data = self.ctx.master.readReg(addr=0x2C, cntbyte=4, datatypelen=1)
        datab = struct.unpack('<f', bytes(data))
        self.et_emit_ratio.SetValue('%.1f' % datab[0])

    def appendText(self, msg, err=False):
        if not err:
            self.et_receive.SetForegroundColour("#000000")
        else:
            self.et_receive.SetForegroundColour("#ff0000")
        self.et_receive.AppendText(msg + "\n")

    def int_to_bytes_list(self, data, length=2, byteorder='little', signed=False):
        if not data:
            return False
        bs = data.to_bytes(length=length, byteorder=byteorder, signed=signed)
        if bs:
            l = list(bs)
            print(l)
            return l

# data=[0x00,0x00,0x80,0x3f]
# datab = struct.unpack('<f',bytes(data))
# print(str(datab[0]))

# arr=struct.pack('<f',0.122)
# bytesArr=[]
# for b in arr:
#     print(b)
#     bytesArr.append(b)
# print(type(bytesArr),bytesArr)
#
# datab=struct.unpack('<f',bytes(bytesArr))
# print(str(datab[0]))
